package thread;

/**
 * NEW->RUNNABLE->BLOCKED->RUNNABLE->TERMINATED
 */
public class ThreadStateNRBRT {
    //锁
    private static final Object lock = new Object();

    public static void main(String[] args) {
        //辅助线程，制造synchronized状态。
        Thread assistantThread = new Thread(new SynTask());
        assistantThread.setName("assistantThread");
        assistantThread.start();
        try {
            //保证assistantThread先执行。
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Thread showThread = new Thread(new Task());
        showThread.setName("showThread");
        ThreadUtils.print(showThread.getName(), showThread.getState());  // NEW
        showThread.start();
        ThreadUtils.print(showThread.getName(), showThread.getState()); // RUNNABLE
        //因为无法判断显示线程何时执行，所以循环直到显示线程执行。
        while (true) {
            // 线程状态为BLOCKED时打印并跳出，也即showThread和assistanceThread在竞争锁时才跳出。
            if (showThread.getState() == Thread.State.BLOCKED) {
                ThreadUtils.print(showThread.getName(), Thread.State.BLOCKED); // BLOCKED
                break;
            }
        }
        //等待两个线程执行完毕。
        try {
            assistantThread.join();
            showThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //线程执行完毕打印状态。
        ThreadUtils.print(showThread.getName(), showThread.getState());
    }

    private static class SynTask implements Runnable {
        @Override
        public void run() {
            //锁定一定时间
            synchronized (lock) {
                try {
                    System.out.println("SynTask#run()");
                    // 让assistantThread拿到锁并阻塞住showThread
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static class Task implements Runnable {
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("Task#run()");
                ThreadUtils.print(Thread.currentThread().getName(), Thread.currentThread().getState());
            }
        }
    }

}
